#pragma once

#include <string>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <netinet/tcp.h>
#include <sys/socket.h>

class Socket {
public:
    explicit Socket(int sockfd) : sockfd_(sockfd) {
        setReuseAddr(true);
    }
    ~Socket();

    int fd() const { return sockfd_; }

    void bindAddress(int port);
    void listening();

    int accept();

    void shutdownWrite();

    // 设置是否开启端口复用 SO_REUSEADDR
    void setReuseAddr(bool on);
    // 设置是否开启 TCP_NODELAY (Nagle算法)
    void setTcpNoDelay(bool on);
    // 设置TCP keep alive
    void setKeepAlive(bool on);

private:
    const int sockfd_;

};

int createNonblockingSocket();
int getSocketError(int sockfd);

struct sockaddr* sockaddr_cast(struct sockaddr_in* addr);
struct sockaddr_in getLocalAddr(int sockfd);
struct sockaddr_in getPeerAddr(int sockfd);
bool isSelfConnect(int sockfd);

std::string toIp(struct sockaddr_in addr);
std::string toIpPort(struct sockaddr_in addr);
uint16_t toPort(struct sockaddr_in addr);
